package com.pai4j.zwiki.service.agent;

import com.pai4j.zwiki.domain.entity.CodeStructureEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 智能文件优先级排序器
 * 
 * 核心功能：
 * 1. 根据文件重要性智能排序，优先阅读重要文件
 * 2. 考虑多个维度：文件类型、依赖关系、代码量、修改频率等
 * 3. 识别关键路径上的文件
 * 4. 优先处理业务核心文件
 * 5. 动态调整优先级
 *
 * 优先级评分因素：
 * - 文件类型（Application > Controller > Service > Repository > Entity > Util）
 * - 被依赖次数（核心类优先）
 * - 代码行数（适中的文件优先，过大过小都降低优先级）
 * - 包深度（顶层包优先）
 * - 命名特征（核心业务相关的优先）
 *
 * @author pai4j
 * @since 2025-10-14
 */
@Slf4j
@Service
public class IntelligentFilePrioritizer {

    /**
     * 对文件列表进行智能排序
     */
    public List<CodeStructureEntity> prioritizeFiles(List<CodeStructureEntity> structures,
                                                     Map<String, Set<String>> dependencyGraph) {
        log.info("开始智能文件优先级排序，文件总数: {}", structures.size());

        // 计算每个文件的优先级分数
        Map<CodeStructureEntity, Double> scores = new HashMap<>();

        for (CodeStructureEntity structure : structures) {
            double score = calculatePriorityScore(structure, structures, dependencyGraph);
            scores.put(structure, score);
        }

        // 按分数排序
        List<CodeStructureEntity> sorted = scores.entrySet().stream()
                .sorted((e1, e2) -> Double.compare(e2.getValue(), e1.getValue()))
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());

        log.info("文件优先级排序完成");
        logTopFiles(sorted, scores);

        return sorted;
    }

    /**
     * 计算文件的优先级分数（0-100）
     */
    private double calculatePriorityScore(CodeStructureEntity structure,
                                          List<CodeStructureEntity> allStructures,
                                          Map<String, Set<String>> dependencyGraph) {
        double score = 0.0;

        // 1. 文件类型权重（35分）
        score += calculateTypeScore(structure) * 35;

        // 2. 被依赖次数权重（30分）
        score += calculateDependencyScore(structure, dependencyGraph) * 30;

        // 3. 代码量权重（15分）- 适中的文件优先
        score += calculateSizeScore(structure) * 15;

        // 4. 包深度权重（10分）- 顶层包优先
        score += calculatePackageDepthScore(structure) * 10;

        // 5. 命名特征权重（10分）- 核心业务词汇
        score += calculateNamingScore(structure) * 10;

        return score;
    }

    /**
     * 计算文件类型分数（0-1）
     */
    private double calculateTypeScore(CodeStructureEntity structure) {
        String name = structure.getName();

        // 启动类最重要
        if (name.contains("Application") && !name.contains("Test")) {
            return 1.0;
        }

        // Controller次之
        if (name.endsWith("Controller")) {
            return 0.9;
        }

        // Configuration
        if (name.endsWith("Config") || name.endsWith("Configuration")) {
            return 0.85;
        }

        // Service
        if (name.endsWith("Service") && !name.endsWith("ServiceImpl")) {
            return 0.8;
        }

        // ServiceImpl
        if (name.endsWith("ServiceImpl")) {
            return 0.75;
        }

        // Repository/DAO
        if (name.endsWith("Repository") || name.endsWith("Dao")) {
            return 0.7;
        }

        // Entity/Model
        if (name.endsWith("Entity") || name.endsWith("Model") || name.endsWith("DTO")) {
            return 0.6;
        }

        // Util/Helper
        if (name.contains("Util") || name.contains("Helper")) {
            return 0.4;
        }

        // 其他
        return 0.5;
    }

    /**
     * 计算依赖分数（0-1）
     */
    private double calculateDependencyScore(CodeStructureEntity structure,
                                            Map<String, Set<String>> dependencyGraph) {
        String fullName = structure.getPackageName() + "." + structure.getName();

        // 计算被依赖次数
        long inDegree = dependencyGraph.values().stream()
                .flatMap(Set::stream)
                .filter(dep -> dep.equals(fullName))
                .count();

        // 归一化到0-1
        return Math.min(1.0, inDegree / 10.0);
    }

    /**
     * 计算代码量分数（0-1）
     */
    private double calculateSizeScore(CodeStructureEntity structure) {
        Integer lineCount = structure.getLineCount();
        if (lineCount == null) return 0.5;

        // 最佳代码量：100-300行
        if (lineCount >= 100 && lineCount <= 300) {
            return 1.0;
        }

        // 50-500行也可以
        if (lineCount >= 50 && lineCount <= 500) {
            return 0.8;
        }

        // 太小（<50行）或太大（>500行）降低优先级
        if (lineCount < 50) {
            return 0.4;
        }

        if (lineCount > 500) {
            return 0.6;
        }

        return 0.5;
    }

    /**
     * 计算包深度分数（0-1）
     */
    private double calculatePackageDepthScore(CodeStructureEntity structure) {
        String packageName = structure.getPackageName();
        if (packageName == null) return 0.5;

        int depth = packageName.split("\\.").length;

        // 3-4层深度最佳（如com.example.project）
        if (depth >= 3 && depth <= 4) {
            return 1.0;
        }

        // 5-6层也可以
        if (depth >= 5 && depth <= 6) {
            return 0.7;
        }

        // 太深或太浅降低优先级
        return 0.5;
    }

    /**
     * 计算命名特征分数（0-1）
     */
    private double calculateNamingScore(CodeStructureEntity structure) {
        String name = structure.getName().toLowerCase();
        String packageName = structure.getPackageName().toLowerCase();

        double score = 0.0;

        // 核心业务词汇
        String[] coreKeywords = {"user", "order", "product", "payment", "auth", "main", "core"};
        for (String keyword : coreKeywords) {
            if (name.contains(keyword) || packageName.contains(keyword)) {
                score += 0.3;
            }
        }

        // 基础设施词汇
        String[] infraKeywords = {"base", "common", "util", "helper", "tool"};
        for (String keyword : infraKeywords) {
            if (name.contains(keyword) || packageName.contains(keyword)) {
                score += 0.1;
            }
        }

        return Math.min(1.0, score);
    }

    /**
     * 记录前N个文件的优先级
     */
    private void logTopFiles(List<CodeStructureEntity> sorted, 
                            Map<CodeStructureEntity, Double> scores) {
        log.info("=== 前10个高优先级文件 ===");
        for (int i = 0; i < Math.min(10, sorted.size()); i++) {
            CodeStructureEntity file = sorted.get(i);
            double score = scores.get(file);
            log.info("{}. {} - 分数: {}", 
                    i + 1, file.getName(), String.format("%.2f", score));
        }
    }

    /**
     * 获取核心文件（用于深度阅读）
     */
    public List<CodeStructureEntity> getCoreFilesForDeepReading(
            List<CodeStructureEntity> structures,
            Map<String, Set<String>> dependencyGraph,
            int topN) {
        
        List<CodeStructureEntity> prioritized = prioritizeFiles(structures, dependencyGraph);
        
        // 取前topN个文件
        return prioritized.stream()
                .limit(topN)
                .collect(Collectors.toList());
    }

    /**
     * 分批获取文件（增量式阅读）
     */
    public List<List<CodeStructureEntity>> batchFiles(List<CodeStructureEntity> structures,
                                                       Map<String, Set<String>> dependencyGraph,
                                                       int batchSize) {
        List<CodeStructureEntity> prioritized = prioritizeFiles(structures, dependencyGraph);
        
        List<List<CodeStructureEntity>> batches = new ArrayList<>();
        for (int i = 0; i < prioritized.size(); i += batchSize) {
            int end = Math.min(i + batchSize, prioritized.size());
            batches.add(new ArrayList<>(prioritized.subList(i, end)));
        }

        log.info("文件分批完成: 总共{}个文件，分为{}批，每批{}个", 
                prioritized.size(), batches.size(), batchSize);

        return batches;
    }
}

